package com.cie2.janji.services;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;

import com.cie2.janji.entities.BEPromiseStatistics;
import com.cie2.janji.entities.BaseEntity;
import com.cie2.janji.entities.Category;
import com.cie2.janji.entities.Promise;
import com.cie2.janji.entities.PromiseCategory;
import com.cie2.janji.entities.PromiseStatistics;

public class PromiseStatisticsService {

	private Session session;
	private BaseEntityService entityService;
	
	public PromiseStatisticsService(Session session, BaseEntityService entityService) {
		this.session = session;
		this.entityService = entityService;
	}
	
	public void createEntityStatistics(BaseEntity entity) {
		PromiseStatistics statistics = new PromiseStatistics();
		
		statistics.setEntity(entity);
		statistics.setTotalPromise(0);
		statistics.setBrokenPromise(0);
		statistics.setRealizedPromise(0);
		statistics.setUnrealizedPromise(0);
		
		session.persist(statistics);
		session.flush();
		//butuh month ama year gak ? terus method untuk pindah bulan / tahun gimana ?
	}
	
	// duluan mana sama create entity ? 
	public void createCategoryStatistics(BaseEntity entity, Category category) {
		PromiseCategory statistics = new PromiseCategory();
		
		statistics.setEntity(entity);
		statistics.setCategory(category);
		statistics.setTotalPromise(0);
		statistics.setBrokenPromise(0);
		statistics.setRealizedPromise(0);
		statistics.setUnrealizedPromise(0);
		
		session.persist(statistics);
		session.flush();
	}
	
	/**
	 * @Todo change this if we decide to use the month and year
	 * @param promise
	 */
	public void addPromise(Promise promise) {
		PromiseStatistics ps = (PromiseStatistics) session.createCriteria(PromiseStatistics.class)
			.add(Restrictions.eq("entity", promise.getEntity())).uniqueResult();
		
		ps.setTotalPromise(ps.getTotalPromise() +1);
		ps.setUnrealizedPromise(ps.getUnrealizedPromise() +1);
		
		session.update(ps);
		session.flush();
		
		
		PromiseCategory pc = (PromiseCategory) session.createCriteria(PromiseCategory.class)
			.add(Restrictions.and(
					Restrictions.eq("entity", promise.getEntity()) ,
					Restrictions.eq("category", promise.getCategory())
					
			))
			.uniqueResult();
		
		if(null == pc)
			System.out.println("=== PC IS NULL ");
			
		pc.setTotalPromise(pc.getTotalPromise() +1);
		pc.setUnrealizedPromise(pc.getUnrealizedPromise() +1);
		
		session.update(pc);
		session.flush();
		
	}
		
	/**
	 * update promise statistics
	 * bakal jadi problem kalo promisenya udah ke realized, boleh di edit selama unrealized aja ? 
	 */
	public void updatePromiseEntityStatistic(Promise oldPromise, Long newEntityId) {
		PromiseStatistics ps = (PromiseStatistics) session.createCriteria(PromiseStatistics.class)
			.add(Restrictions.eq("entity", oldPromise.getEntity())).uniqueResult();
	
		ps.setTotalPromise(ps.getTotalPromise() -1);
		ps.setUnrealizedPromise(ps.getUnrealizedPromise() -1);
			
		session.update(ps);
		
		ps =	(PromiseStatistics) session.createCriteria(PromiseStatistics.class)
			.add(Restrictions.eq("entity.id", newEntityId)).uniqueResult();
		
		ps.setTotalPromise(ps.getTotalPromise() +1);
		ps.setUnrealizedPromise(ps.getUnrealizedPromise() +1);
		
		session.update(ps);
		session.flush();
	}
	
	/**
	 * idem , realized problem
	 * @param oldPromise
	 * @param newCategoryId
	 */
	public void updatePromiseCategoryStatistic(Promise oldPromise, Long newCategoryId) {

		PromiseCategory pc = (PromiseCategory) session.createCriteria(
				PromiseCategory.class).add(
				Restrictions.and(Restrictions.eq("entity", oldPromise
						.getEntity()), Restrictions.eq("category", oldPromise
						.getCategory())

				)).uniqueResult();

		pc.setTotalPromise(pc.getTotalPromise() - 1);
		pc.setUnrealizedPromise(pc.getUnrealizedPromise() - 1);
		
		session.update(pc);
		
		pc = (PromiseCategory) session.createCriteria(
				PromiseCategory.class).add(
				Restrictions.and(Restrictions.eq("entity", oldPromise
						.getEntity()), Restrictions.eq("category.id", newCategoryId)

				)).uniqueResult();	
		
		pc.setTotalPromise(pc.getTotalPromise() + 1);
		pc.setUnrealizedPromise(pc.getUnrealizedPromise() + 1);
		
		session.update(pc);
		session.flush();
	}
	
	
	public void brokePromise(Promise promise) {
	
	}
	
	public void extendPromise(Promise promise) {
		
	}
	
	public void completePromise(Promise promise) {
		
	}

	public PromiseStatistics getStatistics(BaseEntity entity) {
		return (PromiseStatistics) session.createCriteria(PromiseStatistics.class)
		.add(Restrictions.eq("entity", entity)).uniqueResult();		
	}
	
	public List getPC(BaseEntity entity) {
		return session.createCriteria(PromiseCategory.class)
			.add(Restrictions.eq("entity", entity)).list();
	}
	
	public PromiseStatistics getSBYStatistics() {

		return getStatistics(entityService.getByName("sby"));
	}
	
	public List getSBYPCList() {
		return getPC(entityService.getByName("sby"));
	}

	public PromiseStatistics getMegaStatistics() {

		return getStatistics(entityService.getByName("mega"));
	}

	public List getMegaPCList() {
		return getPC(entityService.getByName("mega"));
	}
	
	public PromiseStatistics getJKStatistics() {

		return getStatistics(entityService.getByName("jk"));
	}
	
	public List getJKPCList() {
		return getPC(entityService.getByName("jk"));
	}
	
	
	public void createBEPromiseStatistics() {
		
	}
	
	public BEPromiseStatistics getBEPromiseStatistics(BaseEntity entity) {
		return (BEPromiseStatistics) session.createCriteria(BEPromiseStatistics.class)
			.add(Restrictions.eq("entity", entity)).uniqueResult();
	}
}
